
package com.hlkj.pay.app.merchant.ext.impl.gtzfpay;
/*
 * Hlpay-Plus aggregate payment system.
 * Copyright (c) 2024-2025 Hlpay Team Copyright has the right of final interpretation.
 */

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.hlkj.framework.common.pojo.CommonResult;
import com.hlkj.framework.common.util.json.JsonUtils;
import com.hlkj.framework.extension.annotation.Extension;
import com.hlkj.pay.app.common.IUploadService;
import com.hlkj.pay.app.merchant.ext.ChannelMerchantAccessExtPt;
import com.hlkj.pay.app.merchant.ext.MerchantExtConstant;
import com.hlkj.pay.app.merchant.ext.dto.access.*;
import com.hlkj.pay.app.merchant.ext.impl.gtzfpay.dto.GtzfPayConfig;
import com.hlkj.pay.app.merchant.ext.impl.gtzfpay.dto.GtzfpayAppChannelParams;
import com.hlkj.pay.app.merchant.ext.impl.gtzfpay.handler.GtzfPayMerchantAccessConfigHandler;
import com.hlkj.pay.app.merchant.ext.impl.gtzfpay.handler.GtzfPayMerchantAccessInfoHandler;
import com.hlkj.pay.app.merchant.ext.impl.gtzfpay.utils.GtzfPayCallBackParamsParseUtil;
import com.hlkj.pay.app.merchant.ext.impl.gtzfpay.utils.GtzfPayRsaUtil;
import com.hlkj.pay.dto.merchant.AccessChannelParamsDto;
import com.hlkj.pay.dto.merchant.MerchantAccessDto;
import com.hlkj.pay.enums.CommonEnum;
import com.hlkj.pay.enums.MerchantEnum;
import com.hlkj.pay.infrastructure.model.merchant.MerchantAccessAuthDO;
import com.hlkj.pay.infrastructure.model.merchant.MerchantAccessInfoDO;
import com.hlkj.pay.infrastructure.model.pay.ProviderChannelConfigDO;
import com.hlkj.pay.util.HttpRequestUtil;
import com.hlkj.pay.vo.order.resp.MerchantProductQueryResp;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Repository;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 汇付进件操作
 * 
 * @author HlpayTeam
 * @date 2024/09/26 10:25
 */
@Slf4j
@Repository
@RequiredArgsConstructor
@Extension(bizId = MerchantExtConstant.CHANNEL_GTZF_PAY)
public class GtzfPayMerchantAccessExtPt implements ChannelMerchantAccessExtPt {

    private final IUploadService uploadService;

    private final GtzfPayMerchantAccessInfoHandler gtzfPayMerchantAccessInfoHandler;

    private final GtzfPayMerchantAccessConfigHandler gtzfPayMerchantAccessConfigHandler;

    @Override
    public void channelConfigCheck(ChannelMerchantAccessCommonContext channelMerchantAccessCommonContext) {

    }
    @Override
    public void merchantAccess(ChannelMerchantAccessContext channelMerchantAccessContext) {
        log.info("国通支付提交进件 请求参数:{}", JsonUtils.toJsonString(channelMerchantAccessContext));
        if (channelMerchantAccessContext.isProcessStatus()) {
            gtzfPayMerchantAccessInfoHandler.merchantAccess(channelMerchantAccessContext);
        }
    }

    @Override
    public String requestUrl(MerchantAccessDto merchantAccessInfoDO) {
        return null;
    }

    @Override
    public String channelParams(AccessChannelParamsDto accessChannelParamsDto) {
        GtzfpayAppChannelParams gtzfpayAppChannelParams = new GtzfpayAppChannelParams();
        gtzfpayAppChannelParams.setCustId(accessChannelParamsDto.getSubMchId());
        return JsonUtils.toJsonStringNotNull(gtzfpayAppChannelParams);
    }

    @Override
    public void merchantAccessQuery(ChannelMerchantAccessQueryContext channelMerchantAccessQueryContext) {
        MerchantAccessInfoDO merchantAccessInfoDO = channelMerchantAccessQueryContext.getMerchantAccessInfo();
        if (!StringUtils.hasText(merchantAccessInfoDO.getApplyNo()) && !StringUtils.hasText(merchantAccessInfoDO.getSubMchId())) {
            channelMerchantAccessQueryContext.setProcessStatus(Boolean.FALSE);
            channelMerchantAccessQueryContext.setRemark("申请单号和商户号不能都为空");
            return;
        }
        gtzfPayMerchantAccessInfoHandler.accessQueryRequest(channelMerchantAccessQueryContext);
    }

    @Override
    public void merchantSign(ChannelMerchantAccessSignContext channelMerchantAccessSignContext) {
        // 国通支付的业务开通就是电子协议生成 和签署电子协议
        gtzfPayMerchantAccessInfoHandler.getSignH5Url(channelMerchantAccessSignContext);
//        gtzfPayMerchantAccessInfoHandler.sendAxqCode(channelMerchantAccessSignContext);
//        if (channelMerchantAccessSignContext.isProcessStatus()) {
//            gtzfPayMerchantAccessInfoHandler.previewContract(channelMerchantAccessSignContext);
//        }
    }

    @Override
    public void merchantSignQuery(ChannelMerchantAccessSignContext channelMerchantAccessSignContext) {
//        gtzfPayMerchantAccessInfoHandler.supplementary(channelMerchantAccessSignContext);
    }

    @Override
    public void merchantBusinessOpen(ChannelMerchantBusinessContext channelMerchantBusinessContext) {
        MerchantAccessInfoDO merchantAccessInfo = channelMerchantBusinessContext.getMerchantAccessDto().getMerchantAccessInfo();
        MerchantEnum.CHANNEL_CONFIG_STATUS accessStatus = MerchantEnum.CHANNEL_CONFIG_STATUS.from(merchantAccessInfo.getAuditStatus());
        switch (accessStatus) {
            case SUBMERINFO:
                gtzfPayMerchantAccessConfigHandler.processSubMerInfoQuery(channelMerchantBusinessContext);
                break;
            case WECHAT_CONFIG:
                ChannelMerchantAccessAuthQueryContext channelMerchantAccessAuthQueryContext = new ChannelMerchantAccessAuthQueryContext();
                channelMerchantAccessAuthQueryContext.setMerchantAccessInfo(channelMerchantBusinessContext.getMerchantAccessDto().getMerchantAccessInfo());
                channelMerchantAccessAuthQueryContext.setProviderChannelConfig(channelMerchantBusinessContext.getProviderChannelConfig());
                channelMerchantAccessAuthQueryContext.setMerchantAccessAuthList(channelMerchantBusinessContext.getMerchantAccessAuthList());
                gtzfPayMerchantAccessConfigHandler.processWxAuthQuery(channelMerchantAccessAuthQueryContext);
                break;
            case SIGN:
//                 gtzfPayMerchantAccessInfoHandler.processElecContract(channelMerchantBusinessContext);
                break;
            case SUBMIT:
//                channelMerchantBusinessContext.setAccessStatus(MerchantEnum.ACCESS_STATUS.WAIT_SET);
//                channelMerchantBusinessContext.setAuditStatus(MerchantEnum.CHANNEL_CONFIG_STATUS.SUBMIT);
//                gtzfPayMerchantAccessInfoHandler.accessQueryRequest(channelMerchantBusinessContext);
                break;
            case AUDITING:
                // 审核中
                ChannelMerchantAccessQueryContext channelMerchantAccessQueryContext = new ChannelMerchantAccessQueryContext();
                channelMerchantAccessQueryContext.setMerchantAccessInfo(channelMerchantBusinessContext.getMerchantAccessDto().getMerchantAccessInfo());
                channelMerchantAccessQueryContext.setProviderChannelConfig(channelMerchantBusinessContext.getProviderChannelConfig());
                gtzfPayMerchantAccessInfoHandler.accessQueryRequest(channelMerchantAccessQueryContext);
                if (channelMerchantBusinessContext.isProcessStatus()) {
                    channelMerchantBusinessContext.setAuditStatus(MerchantEnum.CHANNEL_CONFIG_STATUS.WECHAT_CONFIG);
                    channelMerchantBusinessContext.setAccessStatus(MerchantEnum.ACCESS_STATUS.APPROVE_SUCCESS);
                }
        }

    }

    @Override
    public void wechatConfigInit(ChannelMerchantBusinessContext channelMerchantBusinessContext) {
//        gtzfPayMerchantAccessConfigHandler.wechatConfigInit(channelMerchantBusinessContext);
        channelMerchantBusinessContext.setAuditStatus(MerchantEnum.CHANNEL_CONFIG_STATUS.WECHAT_CONFIGING);
    }

    @Override
    public void wechatConfigAdd(ChannelMerchantBusinessContext channelMerchantBusinessContext) {
        // 获取子商户信息进行微信参数配置
        gtzfPayMerchantAccessConfigHandler.processWxAuth(channelMerchantBusinessContext);
    }

    @Override
    public void wechatConfigQuery(ChannelMerchantAccessAuthQueryContext channelMerchantAccessAuthQueryContext) {
        gtzfPayMerchantAccessConfigHandler.processWxConfigQuery(channelMerchantAccessAuthQueryContext);
    }

    @Override
    public void wechatAuthConfig(ChannelMerchantBusinessContext channelMerchantBusinessContext) {
        // 国通支付 为自动认证无需处理
        channelMerchantBusinessContext.setAuditStatus(MerchantEnum.CHANNEL_CONFIG_STATUS.WECHAT_AUTHING);
    }

    @Override
    public boolean authConfigQueryType() {
        return true;
    }

    @Override
    public void wechatAuthQuery(ChannelMerchantAccessAuthQueryContext channelMerchantAccessAuthQueryContext) {
        gtzfPayMerchantAccessConfigHandler.processWxAuthQuery(channelMerchantAccessAuthQueryContext);
        List<MerchantAccessAuthDO> merchantAccessAuthList = channelMerchantAccessAuthQueryContext.getMerchantAccessAuthDbList();
        MerchantAccessInfoDO merchantAccessInfo = channelMerchantAccessAuthQueryContext.getMerchantAccessInfo();
        if (!CollectionUtils.isEmpty(merchantAccessAuthList)) {
            merchantAccessAuthList.stream().forEach(merchantAccessAuthDO -> {
                merchantAccessAuthDO.setType(1);
                merchantAccessAuthDO.setSn(merchantAccessInfo.getSn());
                merchantAccessAuthDO.setAccessId(merchantAccessInfo.getId());
                if (merchantAccessAuthDO.getQrCodeArray() != null && merchantAccessAuthDO.getQrCodeArray().length > 0) {
                    CommonResult<String> commonResult = uploadService.upload(merchantAccessAuthDO.getQrCodeArray(), CommonEnum.OssEnum.IMAGE);
                    merchantAccessAuthDO.setAuthUrl(commonResult.getData());
                }
            });
        }
        channelMerchantAccessAuthQueryContext.setAuditStatus(MerchantEnum.CHANNEL_CONFIG_STATUS.ALIPAY_AUTH);
    }

    @Override
    public void alipayAuthConfig(ChannelMerchantBusinessContext channelMerchantBusinessContext) {
//        gtzfPayMerchantAccessConfigHandler.processAliAuth(channelMerchantBusinessContext);
        // 支付宝参数配置
        // 国通支付 为自动认证无需处理
        channelMerchantBusinessContext.setAuditStatus(MerchantEnum.CHANNEL_CONFIG_STATUS.ALIPAY_AUTHING);
    }

    @Override
    public void alipayAuthQuery(ChannelMerchantAccessAuthQueryContext channelMerchantAccessAuthQueryContext) {
        gtzfPayMerchantAccessConfigHandler.processAliAuthQuery(channelMerchantAccessAuthQueryContext);
        List<MerchantAccessAuthDO> merchantAccessAuthList = channelMerchantAccessAuthQueryContext.getMerchantAccessAuthDbList();
        MerchantAccessInfoDO merchantAccessInfo = channelMerchantAccessAuthQueryContext.getMerchantAccessInfo();
        if (!CollectionUtils.isEmpty(merchantAccessAuthList)) {
            merchantAccessAuthList.stream().forEach(merchantAccessAuthDO -> {
                merchantAccessAuthDO.setType(2);
                merchantAccessAuthDO.setSn(merchantAccessInfo.getSn());
                merchantAccessAuthDO.setAccessId(merchantAccessInfo.getId());
            });
        }
        channelMerchantAccessAuthQueryContext.setAuditStatus(MerchantEnum.CHANNEL_CONFIG_STATUS.FINISH);
    }

    @Override
    public MerchantAccessCallBackDto accessCallBackParamsParse(HttpServletRequest request, ProviderChannelConfigDO providerChannelConfigDO) {
        String accessCallBody = HttpRequestUtil.requestBodyParams(request);
        return this.accessCallBackParamsParse(accessCallBody, providerChannelConfigDO);
    }

    @Override
    public CommonResult<String> accessCallbackParse(String callBackBody, List<ProviderChannelConfigDO> channelConfigDOList) {
        JSONObject obj = JSONUtil.parseObj(callBackBody);
        ProviderChannelConfigDO channelConfigDO = channelConfigDOList.stream().filter(channel -> {
            GtzfPayConfig config = JsonUtils.parseObject(channel.getParamsConfig(), GtzfPayConfig.class);
            return config.getAgetId().equals(obj.getStr("agetId"));
        }).findFirst().get();
        GtzfPayConfig config = JsonUtils.parseObject(channelConfigDO.getParamsConfig(), GtzfPayConfig.class);
        String plainText = GtzfPayRsaUtil.decrypt(obj.getStr("pdata"), config.getMchPublicKey());
        log.info("国通支付进件回调  plainText:{}", plainText);
        JSONObject dataObj = JSONUtil.parseObj(plainText);
        return CommonResult.success(dataObj.getStr("CUST_ID"));
    }

    public MerchantAccessCallBackDto accessCallBackParamsParse(String callBackBody, ProviderChannelConfigDO providerChannelConfigDO) {
        String channelConfig = providerChannelConfigDO.getParamsConfig();
        // 配置转换
        GtzfPayConfig config = JsonUtils.parseObject(channelConfig, GtzfPayConfig.class);
        return GtzfPayCallBackParamsParseUtil.accessCallBackParamsParse(callBackBody, config);
    }

    @Override
    public MerchantBusinessCallBackDto businessCallBackParamsParse(String callBackBody, ProviderChannelConfigDO providerChannelConfigDO) {
        String channelConfig = providerChannelConfigDO.getParamsConfig();
        // 配置转换
        GtzfPayConfig config = JsonUtils.parseObject(channelConfig, GtzfPayConfig.class);
        return GtzfPayCallBackParamsParseUtil.businessCallBackParamsParse(callBackBody, config);
    }

    @Override
    public boolean verify(String callBackBody, ProviderChannelConfigDO providerChannelConfigDO) {
        String channelConfig = providerChannelConfigDO.getParamsConfig();
        // 配置转换
        GtzfPayConfig config = JsonUtils.parseObject(channelConfig, GtzfPayConfig.class);
        return GtzfPayRsaUtil.verify(callBackBody, config.getMchPublicKey());
    }

    @Override
    public String callBackResponse(CommonResult commonResult) {
        Map<String, String> retObj = new HashMap<>();
        if (commonResult.isSuccess()) {
            retObj.put("rspCod", "");
            retObj.put("retMsg", "success");
        }
        else {
            retObj.put("rspCod", "9999");
            retObj.put("retMsg", "error");
        }
        return retObj.toString();
    }

    @Override
    public void termAdd(ChannelMerchantTermContext channelMerchantTermContext) {

    }

    @Override
    public void reloadMerchantAuth(ChannelMerchantBusinessContext channelMerchantBusinessContext) {
        gtzfPayMerchantAccessConfigHandler.processSubMerInfoQuery(channelMerchantBusinessContext);
    }

    @Override
    public void channelSplit(ChannelMerchantBusinessContext channelMerchantBusinessContext) {
        // 拆分
//        gtzfPayMerchantAccessConfigHandler.channelSplit(channelMerchantBusinessContext);
    }

    @Override
    public void productUpdate(ChannelMerchantBusinessContext channelMerchantBusinessContext) {

    }

    @Override
    public Integer queryMerAuthStatus(ChannelMerchantAccessAuthQueryContext channelMerchantAccessAuthQueryContext) {
        return null;
    }

    @Override
    public MerchantProductQueryResp productQuery(ChannelMerchantBusinessContext channelMerchantBusinessContext) {
        return null;
    }

    @Override
    public MerchantChannelSplitCallBackDto easySplitCallBackParamsParse(HttpServletRequest request, ProviderChannelConfigDO providerChannelConfigDO) {
        return null;
    }

}
